﻿'use strict';

/* jshint -W040 */
var UI = $.AMUI || {};
var $win = $(window);
var doc = window.document;
var $html = $('html');

UI.VERSION = '2.0.0';

UI.support = {};

UI.support.transition = (function () {
    var transitionEnd = (function () {
        // https://developer.mozilla.org/en-US/docs/Web/Events/transitionend#Browser_compatibility
        var element = doc.body || doc.documentElement;
        var transEndEventNames = {
            WebkitTransition: 'webkitTransitionEnd',
            MozTransition: 'transitionend',
            OTransition: 'oTransitionEnd otransitionend',
            transition: 'transitionend'
        };

        for (var name in transEndEventNames) {
            if (element.style[name] !== undefined) {
                return transEndEventNames[name];
            }
        }
    })();

    return transitionEnd && { end: transitionEnd };
})();

UI.support.animation = (function () {
    var animationEnd = (function () {
        var element = doc.body || doc.documentElement;
        var animEndEventNames = {
            WebkitAnimation: 'webkitAnimationEnd',
            MozAnimation: 'animationend',
            OAnimation: 'oAnimationEnd oanimationend',
            animation: 'animationend'
        };

        for (var name in animEndEventNames) {
            if (element.style[name] !== undefined) {
                return animEndEventNames[name];
            }
        }
    })();

    return animationEnd && { end: animationEnd };
})();

/* jshint -W069 */
UI.support.touch = (
('ontouchstart' in window &&
navigator.userAgent.toLowerCase().match(/mobile|tablet/)) ||
(window.DocumentTouch && document instanceof window.DocumentTouch) ||
(window.navigator['msPointerEnabled'] &&
window.navigator['msMaxTouchPoints'] > 0) || //IE 10
(window.navigator['pointerEnabled'] &&
window.navigator['maxTouchPoints'] > 0) || //IE >=11
false);

// https://developer.mozilla.org/zh-CN/docs/DOM/MutationObserver
UI.support.mutationobserver = (window.MutationObserver ||
window.WebKitMutationObserver || null);

// https://github.com/Modernizr/Modernizr/blob/924c7611c170ef2dc502582e5079507aff61e388/feature-detects/forms/validation.js#L20
UI.support.formValidation = (typeof document.createElement('form').
  checkValidity === 'function');

UI.utils = {};

/**
 * Debounce function
 * @param {function} func  Function to be debounced
 * @param {number} wait Function execution threshold in milliseconds
 * @param {bool} immediate  Whether the function should be called at
 *                          the beginning of the delay instead of the
 *                          end. Default is false.
 * @desc Executes a function when it stops being invoked for n seconds
 * @via  _.debounce() http://underscorejs.org
 */
UI.utils.debounce = function (func, wait, immediate) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        var later = function () {
            timeout = null;
            if (!immediate) {
                func.apply(context, args);
            }
        };
        var callNow = immediate && !timeout;

        clearTimeout(timeout);
        timeout = setTimeout(later, wait);

        if (callNow) {
            func.apply(context, args);
        }
    };
};

UI.utils.isInView = function (element, options) {
    var $element = $(element);
    var visible = !!($element.width() || $element.height()) &&
      $element.css('display') !== 'none';

    if (!visible) {
        return false;
    }

    var windowLeft = $win.scrollLeft();
    var windowTop = $win.scrollTop();
    var offset = $element.offset();
    var left = offset.left;
    var top = offset.top;

    options = $.extend({ topOffset: 0, leftOffset: 0 }, options);

    return (top + $element.height() >= windowTop &&
    top - options.topOffset <= windowTop + $win.height() &&
    left + $element.width() >= windowLeft &&
    left - options.leftOffset <= windowLeft + $win.width());
};

/* jshint -W054 */
UI.utils.parseOptions = UI.utils.options = function (string) {
    if ($.isPlainObject(string)) {
        return string;
    }

    var start = (string ? string.indexOf('{') : -1);
    var options = {};

    if (start != -1) {
        try {
            options = (new Function('',
              'var json = ' + string.substr(start) +
              '; return JSON.parse(JSON.stringify(json));'))();
        } catch (e) {
        }
    }

    return options;
};

/* jshint +W054 */

UI.utils.generateGUID = function (namespace) {
    var uid = namespace + '-' || 'am-';

    do {
        uid += Math.random().toString(36).substring(2, 7);
    } while (document.getElementById(uid));

    return uid;
};


// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
    var called = false;
    var $el = this;

    $(this).one(UI.support.transition.end, function () {
        called = true;
    });

    var callback = function () {
        if (!called) {
            $($el).trigger(UI.support.transition.end);
        }
        $el.transitionEndTimmer = undefined;
    };
    this.transitionEndTimmer = setTimeout(callback, duration);
    return this;
};

$.fn.redraw = function () {
    $(this).each(function () {
        /* jshint unused:false */
        var redraw = this.offsetHeight;
    });
    return this;
};

/* jshint unused:true */

$.fn.transitionEnd = function (callback) {
    var endEvent = UI.support.transition.end;
    var dom = this;

    function fireCallBack(e) {
        callback.call(this, e);
        endEvent && dom.off(endEvent, fireCallBack);
    }

    if (callback && endEvent) {
        dom.on(endEvent, fireCallBack);
    }

    return this;
};

$.fn.removeClassRegEx = function () {
    return this.each(function (regex) {
        var classes = $(this).attr('class');

        if (!classes || !regex) {
            return false;
        }

        var classArray = [];
        classes = classes.split(' ');

        for (var i = 0, len = classes.length; i < len; i++) {
            if (!classes[i].match(regex)) {
                classArray.push(classes[i]);
            }
        }

        $(this).attr('class', classArray.join(' '));
    });
};

//
$.fn.alterClass = function (removals, additions) {
    var self = this;

    if (removals.indexOf('*') === -1) {
        // Use native jQuery methods if there is no wildcard matching
        self.removeClass(removals);
        return !additions ? self : self.addClass(additions);
    }

    var classPattern = new RegExp('\\s' +
    removals.
      replace(/\*/g, '[A-Za-z0-9-_]+').
      split(' ').
      join('\\s|\\s') +
    '\\s', 'g');

    self.each(function (i, it) {
        var cn = ' ' + it.className + ' ';
        while (classPattern.test(cn)) {
            cn = cn.replace(classPattern, ' ');
        }
        it.className = $.trim(cn);
    });

    return !additions ? self : self.addClass(additions);
};

// handle multiple browsers for requestAnimationFrame()
// http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
// https://github.com/gnarf/jquery-requestAnimationFrame
UI.utils.rAF = (function () {
    return window.requestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.oRequestAnimationFrame ||
        // if all else fails, use setTimeout
      function (callback) {
          return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps
      };
})();

// handle multiple browsers for cancelAnimationFrame()
UI.utils.cancelAF = (function () {
    return window.cancelAnimationFrame ||
      window.webkitCancelAnimationFrame ||
      window.mozCancelAnimationFrame ||
      window.oCancelAnimationFrame ||
      function (id) {
          window.clearTimeout(id);
      };
})();

// via http://davidwalsh.name/detect-scrollbar-width
UI.utils.measureScrollbar = function () {
    if (document.body.clientWidth >= window.innerWidth) {
        return 0;
    }

    // if ($html.width() >= window.innerWidth) return;
    // var scrollbarWidth = window.innerWidth - $html.width();
    var $measure = $('<div ' +
    'style="width: 100px;height: 100px;overflow: scroll;' +
    'position: absolute;top: -9999px;"></div>');

    $(document.body).append($measure);

    var scrollbarWidth = $measure[0].offsetWidth - $measure[0].clientWidth;

    $measure.remove();

    return scrollbarWidth;
};

UI.utils.imageLoader = function ($image, callback) {
    function loaded() {
        callback($image[0]);
    }

    function bindLoad() {
        this.one('load', loaded);
        if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
            var src = this.attr('src');
            var param = src.match(/\?/) ? '&' : '?';

            param += 'random=' + (new Date()).getTime();
            this.attr('src', src + param);
        }
    }

    if (!$image.attr('src')) {
        loaded();
        return;
    }

    if ($image[0].complete || $image[0].readyState === 4) {
        loaded();
    } else {
        bindLoad.call($image);
    }
};

/**
 * https://github.com/cho45/micro-template.js
 * (c) cho45 http://cho45.github.com/mit-license
 */
/* jshint -W109 */
UI.template = function (id, data) {
    var me = UI.template;

    if (!me.cache[id]) {
        me.cache[id] = (function () {
            var name = id;
            var string = /^[\w\-]+$/.test(id) ?
              me.get(id) : (name = 'template(string)', id); // no warnings

            var line = 1;
            var body = ('try { ' + (me.variable ?
            'var ' + me.variable + ' = this.stash;' : 'with (this.stash) { ') +
            "this.ret += '" +
            string.
              replace(/<%/g, '\x11').replace(/%>/g, '\x13'). // if you want other tag, just edit this line
              replace(/'(?![^\x11\x13]+?\x13)/g, '\\x27').
              replace(/^\s*|\s*$/g, '').
              replace(/\n/g, function () {
                  return "';\nthis.line = " + (++line) + "; this.ret += '\\n";
              }).
              replace(/\x11-(.+?)\x13/g, "' + ($1) + '").
              replace(/\x11=(.+?)\x13/g, "' + this.escapeHTML($1) + '").
              replace(/\x11(.+?)\x13/g, "'; $1; this.ret += '") +
            "'; " + (me.variable ? "" : "}") + "return this.ret;" +
            "} catch (e) { throw 'TemplateError: ' + e + ' (on " + name +
            "' + ' line ' + this.line + ')'; } " +
            "//@ sourceURL=" + name + "\n" // source map
            ).replace(/this\.ret \+= '';/g, '');
            /* jshint -W054 */
            var func = new Function(body);
            var map = {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '\x22': '&#x22;',
                '\x27': '&#x27;'
            };
            var escapeHTML = function (string) {
                return ('' + string).replace(/[&<>\'\"]/g, function (_) {
                    return map[_];
                });
            };

            return function (stash) {
                return func.call(me.context = {
                    escapeHTML: escapeHTML,
                    line: 1,
                    ret: '',
                    stash: stash
                });
            };
        })();
    }

    return data ? me.cache[id](data) : me.cache[id];
};
/* jshint +W109 */
/* jshint +W054 */

UI.template.cache = {};

UI.template.get = function (id) {
    if (id) {
        var element = document.getElementById(id);
        return element && element.innerHTML || '';
    }
};

// Dom mutation watchers
UI.DOMWatchers = [];
UI.DOMReady = false;
UI.ready = function (callback) {
    UI.DOMWatchers.push(callback);
    if (UI.DOMReady) {
        console.log('ready call');
        callback(document);
    }
};

UI.DOMObserve = function (elements, options, callback) {
    var Observer = UI.support.mutationobserver;
    if (!Observer) {
        return;
    }

    options = $.isPlainObject(options) ?
        options : { childList: true, subtree: true };

    callback = typeof callback === 'function' && callback || function () {
    };

    $(elements).each(function () {
        var element = this;
        var $element = $(element);

        if ($element.data('am.observer')) {
            return;
        }

        try {
            var observer = new Observer(UI.utils.debounce(
              function (mutations, instance) {
                  callback.call(element, mutations, instance);
                  // trigger this event manually if MutationObserver not supported
                  $element.trigger('changed.dom.amui');
              }, 50));

            observer.observe(element, options);

            $element.data('am.observer', observer);
        } catch (e) {
        }
    });
};

$.fn.DOMObserve = function (options, callback) {
    return this.each(function () {
        UI.DOMObserve(this, options, callback);
    });
};


'use strict';
var $doc = $(document);

/**
 * bootstrap-datepicker.js
 * @via http://www.eyecon.ro/bootstrap-datepicker
 * @license http://www.apache.org/licenses/LICENSE-2.0
 */
var Datepicker = function (element, options) {
    this.$element = $(element);
    this.options = $.extend({}, Datepicker.DEFAULTS, options);
    this.format = DPGlobal.parseFormat(this.options.format);

    this.$element.data('date', this.options.date);
    this.language = this.getLocale(this.options.locale);
    this.theme = this.options.theme;
    this.$picker = $(DPGlobal.template).appendTo('body').on({
        click: $.proxy(this.click, this)
        // mousedown: $.proxy(this.mousedown, this)
    });

    this.isInput = this.$element.is('input');
    this.component = this.$element.is('.am-datepicker-date') ?
      this.$element.find('.am-datepicker-add-on') : false;

    if (this.isInput) {
        this.$element.on({
            'click.datepicker.amui': $.proxy(this.open, this),
            // blur: $.proxy(this.close, this),
            'keyup.datepicker.amui': $.proxy(this.update, this)
        });
    }
    else {
        if (this.component) {
            this.component.on('click.datepicker.amui', $.proxy(this.open, this));
        }
        else {
            this.$element.on('click.datepicker.amui', $.proxy(this.open, this));
        }
    }

    this.minViewMode = this.options.minViewMode;

    if (typeof this.minViewMode === 'string') {
        switch (this.minViewMode) {
            case 'months':
                this.minViewMode = 1;
                break;
            case 'years':
                this.minViewMode = 2;
                break;
            default:
                this.minViewMode = 0;
                break;
        }
    }

    this.viewMode = this.options.viewMode;

    if (typeof this.viewMode === 'string') {
        switch (this.viewMode) {
            case 'months':
                this.viewMode = 1;
                break;
            case 'years':
                this.viewMode = 2;
                break;
            default:
                this.viewMode = 0;
                break;
        }
    }

    this.startViewMode = this.viewMode;
    this.weekStart = ((this.options.weekStart ||
      Datepicker.locales[this.language].weekStart || 0) % 7);
    this.weekEnd = ((this.weekStart + 6) % 7);
    this.onRender = this.options.onRender;

    this.setTheme();
    this.fillDow();
    this.fillMonths();
    this.update();
    this.showMode();
};

Datepicker.DEFAULTS = {
    locale: 'zh_CN',
    format: 'yyyy-mm-dd',
    weekStart: undefined,
    viewMode: 0,
    minViewMode: 0,
    date: '',
    theme: '',
    autoClose: 1,
    onRender: function (date) {
        return '';
    }
};

Datepicker.prototype.open = function (e) {
    this.$picker.show();
    this.height = this.component ?
      this.component.outerHeight() : this.$element.outerHeight();

    this.place();
    $(window).on('resize.datepicker.amui', $.proxy(this.place, this));
    if (e) {
        e.stopPropagation();
        e.preventDefault();
    }
    var that = this;
    $(document).on('click.datepicker.amui', function (ev) {
        if ($(ev.target).closest('.am-datepicker').length === 0) {
            that.close();
        }
    });
    this.$element.trigger({
        type: 'open.datepicker.amui',
        date: this.date
    });
};

Datepicker.prototype.close = function () {
    this.$picker.hide();
    $(window).off('resize.datepicker.amui', this.place);
    this.viewMode = this.startViewMode;
    this.showMode();
    if (!this.isInput) {
        $(document).off('click.datepicker.amui', this.close);
    }
    // this.set();
    this.$element.trigger({
        type: 'close.datepicker.amui',
        date: this.date
    });
};

Datepicker.prototype.set = function () {
    var formated = DPGlobal.formatDate(this.date, this.format);
    if (!this.isInput) {
        if (this.component) {
            this.$element.find('input').prop('value', formated);
        }
        this.$element.data('date', formated);
    } else {
        this.$element.prop('value', formated);
    }
};

Datepicker.prototype.setValue = function (newDate) {
    if (typeof newDate === 'string') {
        this.date = DPGlobal.parseDate(newDate, this.format);
    } else {
        this.date = new Date(newDate);
    }
    this.set();

    this.viewDate = new Date(this.date.getFullYear(),
      this.date.getMonth(), 1, 0, 0, 0, 0);

    this.fill();
};

Datepicker.prototype.place = function () {
    var offset = this.component ?
      this.component.offset() : this.$element.offset();
    var $width = this.component ?
      this.component.width() : this.$element.width();
    var top = offset.top + this.height;
    var left = offset.left;
    var right = $doc.width() - offset.left - $width;
    var isOutView = this.isOutView();
    this.$picker.removeClass('am-datepicker-right');
    this.$picker.removeClass('am-datepicker-up');

    if ($doc.width() > 640) {
        if (isOutView.outRight) {
            this.$picker.addClass('am-datepicker-right');
            this.$picker.css({
                top: top,
                left: 'auto',
                right: right
            });
            return;
        }
        if (isOutView.outBottom) {
            this.$picker.addClass('am-datepicker-up');
            top = offset.top - this.$picker.outerHeight(true);
        }
    } else {
        left = 0;
    }
    this.$picker.css({
        top: top,
        left: left
    });
};

Datepicker.prototype.update = function (newDate) {
    this.date = DPGlobal.parseDate(
      typeof newDate === 'string' ? newDate : (this.isInput ?
        this.$element.prop('value') : this.$element.data('date')),
      this.format
    );
    this.viewDate = new Date(this.date.getFullYear(),
      this.date.getMonth(), 1, 0, 0, 0, 0);
    this.fill();
};

// Days of week
Datepicker.prototype.fillDow = function () {
    var dowCount = this.weekStart;
    var html = '<tr>';
    while (dowCount < this.weekStart + 7) {
        // NOTE: do % then add 1
        html += '<th class="am-datepicker-dow">' +
          Datepicker.locales[this.language].daysMin[(dowCount++) % 7] +
        '</th>';
    }
    html += '</tr>';

    this.$picker.find('.am-datepicker-days thead').append(html);
};

Datepicker.prototype.fillMonths = function () {
    var html = '';
    var i = 0;
    while (i < 12) {
        html += '<span class="am-datepicker-month">' +
        Datepicker.locales[this.language].monthsShort[i++] + '</span>';
    }
    this.$picker.find('.am-datepicker-months td').append(html);
};

Datepicker.prototype.fill = function () {
    var d = new Date(this.viewDate);
    var year = d.getFullYear();
    var month = d.getMonth();
    var currentDate = this.date.valueOf();

    var prevMonth = new Date(year, month - 1, 28, 0, 0, 0, 0);
    var day = DPGlobal
      .getDaysInMonth(prevMonth.getFullYear(), prevMonth.getMonth());

    var daysSelect = this.$picker
      .find('.am-datepicker-days .am-datepicker-select');

    if (this.language === 'zh_CN') {
        daysSelect.text(year + Datepicker.locales[this.language].year[0] +
        ' ' + Datepicker.locales[this.language].months[month]);
    } else {
        daysSelect.text(Datepicker.locales[this.language].months[month] +
        ' ' + year);
    }

    prevMonth.setDate(day);
    prevMonth.setDate(day - (prevMonth.getDay() - this.weekStart + 7) % 7);

    var nextMonth = new Date(prevMonth);
    nextMonth.setDate(nextMonth.getDate() + 42);
    nextMonth = nextMonth.valueOf();
    var html = [];

    var className;
    var prevY;
    var prevM;

    while (prevMonth.valueOf() < nextMonth) {
        if (prevMonth.getDay() === this.weekStart) {
            html.push('<tr>');
        }
        className = this.onRender(prevMonth);
        prevY = prevMonth.getFullYear();
        prevM = prevMonth.getMonth();
        if ((prevM < month && prevY === year) || prevY < year) {
            className += ' am-datepicker-old';
        } else if ((prevM > month && prevY === year) || prevY > year) {
            className += ' am-datepicker-new';
        }
        if (prevMonth.valueOf() === currentDate) {
            className += ' am-active';
        }
        html.push('<td class="am-datepicker-day ' +
        className + '">' + prevMonth.getDate() + '</td>');

        if (prevMonth.getDay() === this.weekEnd) {
            html.push('</tr>');
        }
        prevMonth.setDate(prevMonth.getDate() + 1);

    }

    this.$picker.find('.am-datepicker-days tbody')
      .empty().append(html.join(''));

    var currentYear = this.date.getFullYear();

    var months = this.$picker.find('.am-datepicker-months')
      .find('.am-datepicker-select')
      .text(year);
    months = months.end()
      .find('span').removeClass('am-active');

    if (currentYear === year) {
        months.eq(this.date.getMonth()).addClass('am-active');
    }

    html = '';
    year = parseInt(year / 10, 10) * 10;
    var yearCont = this.$picker
      .find('.am-datepicker-years')
      .find('.am-datepicker-select')
      .text(year + '-' + (year + 9))
      .end()
      .find('td');

    year -= 1;
    for (var i = -1; i < 11; i++) {
        html += '<span class="' +
        (i === -1 || i === 10 ? ' am-datepicker-old' : '') +
        (currentYear === year ? ' am-active' : '') + '">' + year + '</span>';
        year += 1;
    }
    yearCont.html(html);
};

Datepicker.prototype.click = function (event) {
    event.stopPropagation();
    event.preventDefault();
    var month;
    var year;

    var $target = $(event.target).closest('span, td, th');
    if ($target.length === 1) {
        switch ($target[0].nodeName.toLowerCase()) {
            case 'th':
                switch ($target[0].className) {
                    case 'am-datepicker-switch':
                        this.showMode(1);
                        break;
                    case 'am-datepicker-prev':
                    case 'am-datepicker-next':
                        this.viewDate['set' + DPGlobal.modes[this.viewMode].navFnc].call(
                          this.viewDate,
                          this.viewDate
                            ['get' + DPGlobal.modes[this.viewMode].navFnc]
                            .call(this.viewDate) +
                          DPGlobal.modes[this.viewMode].navStep *
                          ($target[0].className === 'am-datepicker-prev' ? -1 : 1)
                        );
                        this.fill();
                        this.set();
                        break;
                }
                break;
            case 'span':
                if ($target.is('.am-datepicker-month')) {
                    month = $target.parent().find('span').index($target);
                    this.viewDate.setMonth(month);
                } else {
                    year = parseInt($target.text(), 10) || 0;
                    this.viewDate.setFullYear(year);
                }

                if (this.viewMode !== 0) {
                    this.date = new Date(this.viewDate);
                    this.$element.trigger({
                        type: 'changeDate.datepicker.amui',
                        date: this.date,
                        viewMode: DPGlobal.modes[this.viewMode].clsName
                    });
                }

                this.showMode(-1);
                this.fill();
                this.set();
                break;
            case 'td':
                if ($target.is('.am-datepicker-day') && !$target.is('.am-disabled')) {
                    var day = parseInt($target.text(), 10) || 1;
                    month = this.viewDate.getMonth();
                    if ($target.is('.am-datepicker-old')) {
                        month -= 1;
                    } else if ($target.is('.am-datepicker-new')) {
                        month += 1;
                    }
                    year = this.viewDate.getFullYear();
                    this.date = new Date(year, month, day, 0, 0, 0, 0);
                    this.viewDate = new Date(year, month, Math.min(28, day), 0, 0, 0, 0);
                    this.fill();
                    this.set();
                    this.$element.trigger({
                        type: 'changeDate.datepicker.amui',
                        date: this.date,
                        viewMode: DPGlobal.modes[this.viewMode].clsName
                    });

                    this.options.autoClose && this.close();
                }
                break;
        }
    }
};

Datepicker.prototype.mousedown = function (event) {
    event.stopPropagation();
    event.preventDefault();
};

Datepicker.prototype.showMode = function (dir) {
    if (dir) {
        this.viewMode = Math.max(this.minViewMode,
          Math.min(2, this.viewMode + dir));
    }
    this.$picker.find('>div').hide();
    this.$picker.find('.am-datepicker-' + DPGlobal.modes[this.viewMode].clsName).show();
};

Datepicker.prototype.isOutView = function () {
    var offset = this.component ?
      this.component.offset() : this.$element.offset();
    var isOutView = {
        outRight: false,
        outBottom: false
    };
    var $picker = this.$picker;
    var width = offset.left + $picker.outerWidth(true);
    var height = offset.top + $picker.outerHeight(true) +
      this.$element.innerHeight();

    if (width > $doc.width()) {
        isOutView.outRight = true;
    }
    if (height > $doc.height()) {
        isOutView.outBottom = true;
    }
    return isOutView;
};

Datepicker.prototype.getLocale = function (locale) {
    if (!locale) {
        locale = navigator.language && navigator.language.split('-');
        locale[1] = locale[1].toUpperCase();
        locale = locale.join('_');
    }

    if (!Datepicker.locales[locale]) {
        locale = 'en_US';
    }
    return locale;
};

Datepicker.prototype.setTheme = function () {
    if (this.theme) {
        this.$picker.addClass('am-datepicker-' + this.theme);
    }
};

// Datepicker locales
Datepicker.locales = {
    en_US: {
        days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
          'Friday', 'Saturday'],
        daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
        months: ['January', 'February', 'March', 'April', 'May', 'June',
          'July', 'August', 'September', 'October', 'November', 'December'],
        monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
          'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
        weekStart: 0
    },
    zh_CN: {
        days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
        daysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
        daysMin: ['日', '一', '二', '三', '四', '五', '六'],
        months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月',
          '八月', '九月', '十月', '十一月', '十二月'],
        monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月',
          '七月', '八月', '九月', '十月', '十一月', '十二月'],
        weekStart: 1,
        year: ['年']
    }
};

var DPGlobal = {
    modes: [
      {
          clsName: 'days',
          navFnc: 'Month',
          navStep: 1
      },
      {
          clsName: 'months',
          navFnc: 'FullYear',
          navStep: 1
      },
      {
          clsName: 'years',
          navFnc: 'FullYear',
          navStep: 10
      }
    ],

    isLeapYear: function (year) {
        return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
    },

    getDaysInMonth: function (year, month) {
        return [31, (DPGlobal.isLeapYear(year) ? 29 : 28),
          31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
    },

    parseFormat: function (format) {
        var separator = format.match(/[.\/\-\s].*?/);
        var parts = format.split(/\W+/);

        if (!separator || !parts || parts.length === 0) {
            throw new Error('Invalid date format.');
        }

        return {
            separator: separator,
            parts: parts
        };
    },

    parseDate: function (date, format) {
        var parts = date.split(format.separator);
        var val;
        date = new Date();

        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);

        if (parts.length === format.parts.length) {
            var year = date.getFullYear();
            var day = date.getDate();
            var month = date.getMonth();

            for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
                val = parseInt(parts[i], 10) || 1;
                switch (format.parts[i]) {
                    case 'dd':
                    case 'd':
                        day = val;
                        date.setDate(val);
                        break;
                    case 'mm':
                    case 'm':
                        month = val - 1;
                        date.setMonth(val - 1);
                        break;
                    case 'yy':
                        year = 2000 + val;
                        date.setFullYear(2000 + val);
                        break;
                    case 'yyyy':
                        year = val;
                        date.setFullYear(val);
                        break;
                }
            }
            date = new Date(year, month, day, 0, 0, 0);
        }
        return date;
    },

    formatDate: function (date, format) {
        var val = {
            d: date.getDate(),
            m: date.getMonth() + 1,
            yy: date.getFullYear().toString().substring(2),
            yyyy: date.getFullYear()
        };
        var dateArray = [];

        val.dd = (val.d < 10 ? '0' : '') + val.d;
        val.mm = (val.m < 10 ? '0' : '') + val.m;

        for (var i = 0, cnt = format.parts.length; i < cnt; i++) {
            dateArray.push(val[format.parts[i]]);
        }
        return dateArray.join(format.separator);
    },

    headTemplate: '<thead>' +
    '<tr class="am-datepicker-header">' +
    '<th class="am-datepicker-prev">' +
    '<i class="am-datepicker-prev-icon"></i></th>' +
    '<th colspan="5" class="am-datepicker-switch">' +
    '<div class="am-datepicker-select"></div></th>' +
    '<th class="am-datepicker-next"><i class="am-datepicker-next-icon"></i>' +
    '</th></tr></thead>',

    contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>'
};

DPGlobal.template = '<div class="am-datepicker am-datepicker-dropdown">' +
'<div class="am-datepicker-caret"></div>' +
'<div class="am-datepicker-days">' +
'<table class="am-datepicker-table">' +
DPGlobal.headTemplate +
'<tbody></tbody>' +
'</table>' +
'</div>' +
'<div class="am-datepicker-months">' +
'<table class="am-datepicker-table">' +
DPGlobal.headTemplate +
DPGlobal.contTemplate +
'</table>' +
'</div>' +
'<div class="am-datepicker-years">' +
'<table class="am-datepicker-table">' +
DPGlobal.headTemplate +
DPGlobal.contTemplate +
'</table>' +
'</div>' +
'</div>';

$.fn.datepicker = function (option, val) {
    return this.each(function () {
        var $this = $(this);
        var data = $this.data('amui.datepicker');

        var options = $.extend({},
          UI.utils.options($this.data('amDatepicker')),
          typeof option === 'object' && option);
        if (!data) {
            $this.data('amui.datepicker', (data = new Datepicker(this, options)));
        }
        if (typeof option === 'string') {
            data[option] && data[option](val);
        }
    });
};

$.fn.datepicker.Constructor = Datepicker;

// Init code
$(document).on('ready', function (e) {
    $('[data-mui-datepicker]').datepicker();
});

